#include "colorsBack.h"

static void pathFind( gameData *player, int xStart, int yStart, int xFinish, int yFinish, int *path, int **m );
static int outBounds( int x, int y, gameData *player );
static int checkColor( gameData *player, int color, int *moves, int x, int y, int dx, int dy, int mode );
static int calcPoints( gameData *player, int chips );

int
playing( const gameData *player1, const gameData *player2 )
{
	return  (checkSlots(player1) || checkSlots(player2) ) &&
		(player1->mode != QUIT && player2->mode != QUIT) &&
		(player1->time - player1->iniTime <= player1->gameTime );
}

int
moveChips( gameData *player, int xStart, int yStart, int xFinish, int yFinish )
{
	int path = 0;
	int **maux;
	if( (maux = newMatrix( player->dimRow, player->dimCol )) == NULL )
		return FAILURE;
	if( outBounds( xStart, yStart, player ) || outBounds( xFinish, yFinish, player ) || 
	  !player->matrix[xStart][yStart] )
		return FAILURE;
	
	if( !player->matrix[xFinish][yFinish] )
	{
		cpyMatrix( player->matrix, maux, player->dimRow, player->dimCol );
		maux[xStart][yStart] = BLANK;
		pathFind( player, xStart, yStart, xFinish, yFinish, &path, maux );
	}
	if( path )
	{
		player->matrix[xFinish][yFinish] = player->matrix[xStart][yStart];
		player->matrix[xStart][yStart] = BLANK;
	}
	freeMatrix( player->dimRow, maux );
	
	return path;
}

void
pathFind( gameData *player, int xStart, int yStart, int xFinish, int yFinish, int *path, int **m )
{
	if( outBounds( xStart, yStart, player ) )
		return;
	if( xStart == xFinish && yStart == yFinish )
		*path = 1;
	if( *path || m[xStart][yStart] )
		return;
	m[xStart][yStart] = 1;
	pathFind( player, xStart+1, yStart, xFinish, yFinish, path, m );
	pathFind( player, xStart, yStart+1, xFinish, yFinish, path, m );
	pathFind( player, xStart-1, yStart, xFinish, yFinish, path, m );
	pathFind( player, xStart, yStart-1, xFinish, yFinish, path, m );
	
	return;
}

int
outBounds( int x, int y, gameData *player )
{
	return x<0 || x>=player->dimRow || y<0 || y>=player->dimCol;
}

int **
newMatrix( int dimRow, int dimCol )
{
	int i;
	int **matrix;
	
	if(matrix = calloc( dimRow, sizeof(int *) ))
		for( i=0; i<dimRow; i++ )
			if( (matrix[i] = calloc( dimCol, sizeof(int) )) == NULL )
				return NULL;
	
	return matrix;
}

void
freeMatrix( int dimRow, int **matrix )
{
	int i;
	
	for( i=0; i<dimRow; i++ )
		free( matrix[i] );
	free( matrix );
}

void
randomChips( gameData *player, int chips )
{
	int i, j, k;
	for( k=0; k<chips; )
	{
		i = rand()% player->dimRow;
		j = rand()% player->dimCol;
		if( player->matrix[i][j] == 0 )
		{
			player->matrix[i][j] = (rand()%player->colors)+1;
			points( player, i, j, player->matrix[i][j] );
			k++;
		}
	}
}

int
checkSlots( const gameData *player )
{
	int flag = 0;
	int i, j;
	
	for( i=0; i<player->dimRow && flag<player->turnChips; i++ )
		for( j=0; j<player->dimCol && flag<player->turnChips; j++ )
			if(player->matrix[i][j] == 0 )
				flag++;
	return flag==player->turnChips;
}



int
ldMatrix( gameData *player, FILE *file )
{
	int i, j;
	if( (player->matrix = newMatrix( player->dimRow, player->dimCol ) ) == NULL )
		return FAILURE;
	for( i=0; i<player->dimRow; i++ )
		for( j=0; j<player->dimCol; j++ )
			player->matrix[i][j] = ((int)fgetc(file))- '0';
	return SUCCESS;
}

void
svMatrix( gameData *player, FILE *file )
{
	int i, j;
	for( i=0; i<player->dimRow; i++ )
		for( j=0; j<player->dimCol; j++ )
			fputc(((char)(player->matrix[i][j] )+'0'), file);
	return;
}


int
points(gameData * player, int x, int y, int color)
{
	int points = 0, totPoints = 0;
	int moves = 0;
	
	
	checkColor( player, color, &moves, x, y, 1, 0, CHECK ); 
	points = calcPoints( player, moves );
	totPoints += points; 
	checkColor( player, color-10, &moves, x, y, 1, 0, points ? ERASE : CLEAN ); 
	if (points)
		player->matrix[x][y]= color;
	moves = 0;
	
	checkColor( player, color, &moves, x, y, 0, 1, CHECK );
	points = calcPoints(player,moves);
	totPoints += points;
	checkColor( player, color-10, &moves, x, y, 0, 1, points ? ERASE : CLEAN );
	if (points)
		player->matrix[x][y]= color;
	moves = 0;
	
	checkColor( player, color, &moves, x, y, 1, 1, CHECK );
	points = calcPoints(player, moves);
	totPoints += points;
	checkColor( player, color-10, &moves, x, y, 1, 1, points ? ERASE : CLEAN );
	if (points)
		player->matrix[x][y]= color;
	moves = 0;
	
	checkColor( player, color, &moves, x, y, -1, 1, CHECK );
	points = calcPoints(player, moves);
	totPoints += points;
	checkColor( player, color-10, &moves, x, y, -1, 1, points ? ERASE : CLEAN );
	if(totPoints)
		player->matrix[x][y]= 0;
	
	return totPoints;
	
}

int 
checkColor( gameData *player, int color, int *moves, int x, int y, int dx, int dy, int mode )
{
	if( outBounds( x, y, player ) || player->matrix[x][y] != color  )
		return 0;
	player->matrix[x][y] += ((mode == CHECK)? -10 : 10);
	if( mode == ERASE )
		player->matrix[x][y] = 0;
	(*moves)++;
	checkColor( player, color, moves, x+dx , y+dy, dx, dy, mode );
	checkColor( player, color, moves, x-dx , y-dy, dx, dy, mode );
	return *moves;
}


int
calcPoints( gameData *player, int chips )
{
	
	int points=0 ;
	
	if ( chips >= player->makeLine )
	{
		chips-=player->makeLine;
		
		switch (chips)
		{
			case 0: points++;
			break;
			case 1: points+=2;
			break; 
			case 2: points+=4;
			break;
			case 3: points+=6;
			break;
			default: points+=8;
		}
	}
	return points;
}

void
undo(gameData * player)
{
	if (player->mode == NORMAL || player->mode == TIME )
		cpyMatrix( player->matrixBack, player->matrix, player->dimRow, player->dimCol );
		player->points = player->pointsBack;
	return;
}

void
cpyMatrix( int **from, int **to, int fil, int col )
{
	int i, j;
	
	for( i=0; i<fil; i++ )
		for( j=0; j<col; j++ )
			to[i][j] = from[i][j];
	return;
}
